using System;
using Microsoft.Ccr.Core;
using System.Net.Sockets;
using Bittorrent.Ccr.Adapters.IO;
using Bittorrent.Agents.Messages;

namespace Bittorrent.Agents
{
    internal class SocketAgent : AgentBase
    {
        private readonly Socket _socket;

        public SocketAgent(Socket socket, DispatcherQueue dispatcherQueue)
            : base(dispatcherQueue) {
            _socket = socket;
            Port = new PortSet<ReadPacket, WritePacket>();

            Activate(
                Arbiter.Interleave(
                    new TeardownReceiverGroup(Arbiter.Receive(false, CleanupPort, s => _socket.Close())),
                    new ExclusiveReceiverGroup(
                        Arbiter.Receive(true, Port.P0, p => ReadPacketHandler(p)),
                        Arbiter.Receive(true, Port.P1, p => WritePacketHandler(p))
                        ),
                    new ConcurrentReceiverGroup()
                    )
                );
        }

        public PortSet<ReadPacket, WritePacket> Port { get; private set; }

        private void WritePacketHandler(WritePacket writePacket) {
            SocketAdapter.Send(_socket, writePacket.Payload, SocketFlags.None, this.TaskQueue, writePacket.ResultPort);
        }

        private void ReadPacketHandler(ReadPacket readPacket) {
            SocketAdapter.Receive(_socket, SocketFlags.None, this.TaskQueue, readPacket.Result);
        }
    }
}
